今天來繼續我們的困難閉包。
尾隨閉包就是當你的閉包做為函數的參數時,可以用尾隨閉包來縮短程式碼的表達式。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数部分
}
// 以下是不使用尾隨閉包的函數調用
someFunctionThatTakesAClosure(closure: {
//閉包部分
})
// 以下是有使用尾隨閉包的版本
someFunctionThatTakesAClosure() {
// 閉包部分
}
而依照前面排序的例子。 sorted(by:) 的方法可以寫成下面的方式。
reversedNames = names.sorted() { $0 > $1 }
而如果閉包表達式是函數的唯一參數可以把 () 省略掉
reversedNames = names.sorted { $0 > $1 }
當閉包長度非常長,無法在一行中寫完時,尾隨閉包就很好使用。
來看官方的例子。
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
官方的例子要用高階函數 map(_:) 來做示範。
然後要做到 Int 轉成 String,所以先做上面的設定。
let strings = numbers.map {
(number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings 會被推斷成 [String]
// 裡面得值獲得到轉換 ["OneSix", "FiveEight", "FiveOneZero"]
接下來當 map 遍歷 numbers 裡面的數值,閉包的 number 會獲得數值,並開始 repeat-while 方法,先檢查數值有沒有大於 0 如果沒有就在裡面循環。
那中間 repeat 裡面在寫什麼呢?
output = digitNames[number % 10]! + output
number /= 10
第一個就是 output 會是 number 求餘 對上的 字典返回 String , 然後 number 會在 除10 繼續循環。
那第一個數值 16 就會先求餘拿到 6 再轉換成Six
之後 number 除10 會拿到 1 再轉換成 One 依此類推。
如果一個函數要使用多個閉包,可以省略第一個尾隨閉包函數的標籤,並未其他尾隨閉包添加標籤。
func loadPicture(from server: Server, completion:(Picture) -> Void,
onFailure: () -> Void) {
if let picture = download("photo.jpg", from: server){
completion(picture)
}else{
onFailure()
}
}
調用的時候長這樣。
loadPicture(from: someServer){ picture in
someView.currentPicture = picture
} onFailure: {
print("Couldn't download the next picture.")
}
上面是第一個閉包是完成處理程序,成功下載並加載圖片。另一個則是錯誤處理。
OK,今天就先到這裡,明天再繼續。